
/* -*- C++ -*- */

//=============================================================================
/*
* @author Feloweria <380374483@qq.com>
* Copyright (C) Feloweria
*
* $ID 2014-05-14 11:26:52 AM
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details
*
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
* @version 1.0
*/
//=============================================================================

#include "Network/SocketBuffer.h"
#include "Network/Socket.h"

FELOWRIA_BEGIN

bool SocketBuffer::Write(const char *bytes, uint32 size)
{
	const uint32 total_size = Writable();
	const uint32 write_size = static_cast<int32>(buffer_end - data_end);

	if (size > total_size)
		return false;

	if (size <= write_size)
	{
		memcpy(data_end, bytes, size);
		data_end += size;
		return true;
	}

	memcpy(data_end, bytes, write_size);

	uint32 last_write_size = size - write_size;

	if (last_write_size)
	{
		memcpy(buffer, bytes + write_size, last_write_size);
		data_end = buffer + last_write_size;
	}

	return true;
}

bool  SocketBuffer::WritePeek(const char *bytes, uint32 size)
{
	const uint32 total_size = Writable();
	const uint32 write_size = static_cast<int32>(buffer_end - data_end);

	char *current = data_end;
	if (!bytes || size > total_size)
		return false;

	if (size <= write_size)
	{
		memcpy(current, bytes, size);
		return true;
	}

	memcpy(current, bytes, write_size);

	uint32 last_write_size = size - write_size;

	if (last_write_size)
		memcpy(buffer, bytes + write_size, last_write_size);

	return true;
}

bool  SocketBuffer::WriteSkip(uint32 size)
{
	const uint32 total_size = Writable();
	const uint32 write_size = static_cast<int32>(buffer_end - data_end);

	if (size > total_size)
		return false;

	if (size <= write_size)
	{
		data_end += size;
		return true;
	}

	data_end = buffer + size - write_size;

	return true;
}

bool  SocketBuffer::Read(char *bytes, uint32 size)
{
	const uint32 total_size = Readable();
	const uint32 read_size = static_cast<int32>(buffer_end - data);

	if (!bytes || size > total_size)
		return false;

	if (size <= read_size)
	{
		memcpy(bytes, data, size);
		data += size;
		return true;
	}

	memcpy(bytes, data, read_size);

	uint32 last_read_size = size - read_size;

	if (last_read_size)
	{
		memcpy(bytes + read_size, buffer, last_read_size);
		data = buffer + last_read_size;
	}
	return true;
}

bool  SocketBuffer::ReadPeek(char *bytes, uint32 size)
{
	const uint32 total_size = Readable();
	const uint32 read_size = static_cast<int32>(buffer_end - data);
	char *current = data;
	if (!bytes || size > total_size)
		return false;

	if (size <= read_size)
	{
		memcpy(bytes, current, size);
		return true;
	}

	memcpy(bytes, current, read_size);

	uint32 last_read_size = size - read_size;

	if (last_read_size)
		memcpy(bytes + read_size, buffer, last_read_size);

	return true;
}

bool  SocketBuffer::ReadSkip(uint32 size)
{
	const uint32 total_size = Readable();
	const uint32 read_size = static_cast<int32>(buffer_end - data);

	if (size > total_size)
		return false;

	if (size <= read_size)
	{
		data += size;
		return true;
	}

	data = buffer + size - read_size;

	return true;
}

FELOWRIA_END
